<!DOCTYPE html>

<html>
<head>
  <title>helpers.coffee</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page_wrapper">
            <div id="jump_page">
              
                
                <a class="source" href="browser.html">
                  browser.coffee
                </a>
              
                
                <a class="source" href="cake.html">
                  cake.coffee
                </a>
              
                
                <a class="source" href="coffeescript.html">
                  coffeescript.coffee
                </a>
              
                
                <a class="source" href="command.html">
                  command.coffee
                </a>
              
                
                <a class="source" href="grammar.html">
                  grammar.coffee
                </a>
              
                
                <a class="source" href="helpers.html">
                  helpers.coffee
                </a>
              
                
                <a class="source" href="index.html">
                  index.coffee
                </a>
              
                
                <a class="source" href="lexer.html">
                  lexer.coffee
                </a>
              
                
                <a class="source" href="nodes.html">
                  nodes.coffee
                </a>
              
                
                <a class="source" href="optparse.html">
                  optparse.coffee
                </a>
              
                
                <a class="source" href="register.html">
                  register.coffee
                </a>
              
                
                <a class="source" href="repl.html">
                  repl.coffee
                </a>
              
                
                <a class="source" href="rewriter.html">
                  rewriter.coffee
                </a>
              
                
                <a class="source" href="scope.html">
                  scope.litcoffee
                </a>
              
                
                <a class="source" href="sourcemap.html">
                  sourcemap.litcoffee
                </a>
              
            </div>
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>helpers.coffee</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-1">&#x00a7;</a>
              </div>
              <p>This file contains the common helper functions that we’d like to share among
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
arrays, count characters, that sort of thing.</p>

            </div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-2">&#x00a7;</a>
              </div>
              <p>Peek at the beginning of a given string to see if it matches a sequence.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.starts = <span class="hljs-function"><span class="hljs-params">(string, literal, start)</span> -&gt;</span>
  literal <span class="hljs-keyword">is</span> string.substr start, literal.length</pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-3">&#x00a7;</a>
              </div>
              <p>Peek at the end of a given string to see if it matches a sequence.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.ends = <span class="hljs-function"><span class="hljs-params">(string, literal, back)</span> -&gt;</span>
  len = literal.length
  literal <span class="hljs-keyword">is</span> string.substr string.length - len - (back <span class="hljs-keyword">or</span> <span class="hljs-number">0</span>), len</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-4">&#x00a7;</a>
              </div>
              <p>Repeat a string <code>n</code> times.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.repeat = repeat = <span class="hljs-function"><span class="hljs-params">(str, n)</span> -&gt;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-5">&#x00a7;</a>
              </div>
              <p>Use clever algorithm to have O(log(n)) string concatenation operations.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  res = <span class="hljs-string">&#x27;&#x27;</span>
  <span class="hljs-keyword">while</span> n &gt; <span class="hljs-number">0</span>
    res += str <span class="hljs-keyword">if</span> n &amp; <span class="hljs-number">1</span>
    n &gt;&gt;&gt;= <span class="hljs-number">1</span>
    str += str
  res</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-6">&#x00a7;</a>
              </div>
              <p>Trim out all falsy values from an array.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.compact = <span class="hljs-function"><span class="hljs-params">(array)</span> -&gt;</span>
  item <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> array <span class="hljs-keyword">when</span> item</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-7">&#x00a7;</a>
              </div>
              <p>Count the number of occurrences of a string in a string.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.count = <span class="hljs-function"><span class="hljs-params">(string, substr)</span> -&gt;</span>
  num = pos = <span class="hljs-number">0</span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>/<span class="hljs-number">0</span> <span class="hljs-keyword">unless</span> substr.length
  num++ <span class="hljs-keyword">while</span> pos = <span class="hljs-number">1</span> + string.indexOf substr, pos
  num</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-8">&#x00a7;</a>
              </div>
              <p>Merge objects, returning a fresh copy with attributes from both sides.
Used every time <code>Base#compile</code> is called, to allow properties in the
options hash to propagate down the tree without polluting other branches.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.merge = <span class="hljs-function"><span class="hljs-params">(options, overrides)</span> -&gt;</span>
  extend (extend {}, options), overrides</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-9">&#x00a7;</a>
              </div>
              <p>Extend a source object with the properties of another object (shallow copy).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>extend = <span class="hljs-built_in">exports</span>.extend = <span class="hljs-function"><span class="hljs-params">(object, properties)</span> -&gt;</span>
  <span class="hljs-keyword">for</span> key, val <span class="hljs-keyword">of</span> properties
    object[key] = val
  object</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-10">&#x00a7;</a>
              </div>
              <p>Return a flattened version of an array.
Handy for getting a list of <code>children</code> from the nodes.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.flatten = flatten = <span class="hljs-function"><span class="hljs-params">(array)</span> -&gt;</span>
  array.flat(<span class="hljs-literal">Infinity</span>)</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-11">&#x00a7;</a>
              </div>
              <p>Delete a key from an object, returning the value. Useful when a node is
looking for a particular method in an options hash.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.del = <span class="hljs-function"><span class="hljs-params">(obj, key)</span> -&gt;</span>
  val =  obj[key]
  <span class="hljs-keyword">delete</span> obj[key]
  val</pre></div></div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-12">&#x00a7;</a>
              </div>
              <p>Typical Array::some</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.some = Array::some ? (fn) -&gt;
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> this <span class="hljs-keyword">when</span> fn e
  <span class="hljs-literal">false</span></pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-13">&#x00a7;</a>
              </div>
              <p>Helper function for extracting code from Literate CoffeeScript by stripping
out all non-code blocks, producing a string of CoffeeScript code that can
be compiled “normally.”</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
  out = []
  blankLine = <span class="hljs-regexp">/^\s*$/</span>
  indented = <span class="hljs-regexp">/^[\t ]/</span>
  listItemStart = <span class="hljs-regexp">/// ^
    (?:\t?|\ {0,3})   <span class="hljs-comment"># Up to one tab, or up to three spaces, or neither;</span>
    (?:
      [\*\-\+] |      <span class="hljs-comment"># followed by `*`, `-` or `+`;</span>
      [0-9]{1,9}\.    <span class="hljs-comment"># or by an integer up to 9 digits long, followed by a period;</span>
    )
    [\ \t]            <span class="hljs-comment"># followed by a space or a tab.</span>
  ///</span>
  insideComment = <span class="hljs-literal">no</span>
  <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> code.split(<span class="hljs-string">&#x27;\n&#x27;</span>)
    <span class="hljs-keyword">if</span> blankLine.test(line)
      insideComment = <span class="hljs-literal">no</span>
      out.push line
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> insideComment <span class="hljs-keyword">or</span> listItemStart.test(line)
      insideComment = <span class="hljs-literal">yes</span>
      out.push <span class="hljs-string">&quot;# <span class="hljs-subst">#{line}</span>&quot;</span>
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> insideComment <span class="hljs-keyword">and</span> indented.test(line)
      out.push line
    <span class="hljs-keyword">else</span>
      insideComment = <span class="hljs-literal">yes</span>
      out.push <span class="hljs-string">&quot;# <span class="hljs-subst">#{line}</span>&quot;</span>
  out.join <span class="hljs-string">&#x27;\n&#x27;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-14">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-14">&#x00a7;</a>
              </div>
              <p>Merge two jison-style location data objects together.
If <code>last</code> is not provided, this will simply return <code>first</code>.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildLocationData</span> = <span class="hljs-params">(first, last)</span> -&gt;</span>
  <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> last
    first
  <span class="hljs-keyword">else</span>
    first_line: first.first_line
    first_column: first.first_column
    last_line: last.last_line
    last_column: last.last_column
    last_line_exclusive: last.last_line_exclusive
    last_column_exclusive: last.last_column_exclusive
    range: [
      first.range[<span class="hljs-number">0</span>]
      last.range[<span class="hljs-number">1</span>]
    ]</pre></div></div>
            
        </li>
        
        
        <li id="section-15">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-15">&#x00a7;</a>
              </div>
              <p>Build a list of all comments attached to tokens.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.extractAllCommentTokens = <span class="hljs-function"><span class="hljs-params">(tokens)</span> -&gt;</span>
  allCommentsObj = {}
  <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.comments
    <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> token.comments
      commentKey = comment.locationData.range[<span class="hljs-number">0</span>]
      allCommentsObj[commentKey] = comment
  sortedKeys = <span class="hljs-built_in">Object</span>.keys(allCommentsObj).sort (a, b) -&gt; a - b
  <span class="hljs-keyword">for</span> key <span class="hljs-keyword">in</span> sortedKeys
    allCommentsObj[key]</pre></div></div>
            
        </li>
        
        
        <li id="section-16">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-16">&#x00a7;</a>
              </div>
              <p>Get a lookup hash for a token based on its location data.
Multiple tokens might have the same location hash, but using exclusive
location data distinguishes e.g. zero-length generated tokens from
actual source tokens.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildLocationHash</span> = <span class="hljs-params">(loc)</span> -&gt;</span>
  <span class="hljs-string">&quot;<span class="hljs-subst">#{loc.range[<span class="hljs-number">0</span>]}</span>-<span class="hljs-subst">#{loc.range[<span class="hljs-number">1</span>]}</span>&quot;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-17">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-17">&#x00a7;</a>
              </div>
              <p>Build a dictionary of extra token properties organized by tokens’ locations
used as lookup hashes.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.buildTokenDataDictionary = buildTokenDataDictionary = <span class="hljs-function"><span class="hljs-params">(tokens)</span> -&gt;</span>
  tokenData = {}
  <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.comments
    tokenHash = buildLocationHash token[<span class="hljs-number">2</span>]</pre></div></div>
            
        </li>
        
        
        <li id="section-18">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-18">&#x00a7;</a>
              </div>
              <p>Multiple tokens might have the same location hash, such as the generated
<code>JS</code> tokens added at the start or end of the token stream to hold
comments that start or end a file.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    tokenData[tokenHash] ?= {}
    <span class="hljs-keyword">if</span> token.comments <span class="hljs-comment"># `comments` is always an array.</span></pre></div></div>
            
        </li>
        
        
        <li id="section-19">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-19">&#x00a7;</a>
              </div>
              <p>For “overlapping” tokens, that is tokens with the same location data
and therefore matching <code>tokenHash</code>es, merge the comments from both/all
tokens together into one array, even if there are duplicate comments;
they will get sorted out later.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      (tokenData[tokenHash].comments ?= []).push token.comments...
  tokenData</pre></div></div>
            
        </li>
        
        
        <li id="section-20">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-20">&#x00a7;</a>
              </div>
              <p>This returns a function which takes an object as a parameter, and if that
object is an AST node, updates that object’s locationData.
The object is returned either way.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.addDataToNode = <span class="hljs-function"><span class="hljs-params">(parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = <span class="hljs-literal">yes</span>)</span> -&gt;</span>
  (obj) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-21">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-21">&#x00a7;</a>
              </div>
              <p>Add location data.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    locationData = buildLocationData(firstValue?.locationData ? firstLocationData, lastValue?.locationData ? lastLocationData)
    <span class="hljs-keyword">if</span> obj?.updateLocationDataIfMissing? <span class="hljs-keyword">and</span> firstLocationData?
      obj.updateLocationDataIfMissing locationData, forceUpdateLocation
    <span class="hljs-keyword">else</span>
      obj.locationData = locationData</pre></div></div>
            
        </li>
        
        
        <li id="section-22">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-22">&#x00a7;</a>
              </div>
              <p>Add comments, building the dictionary of token data if it hasn’t been
built yet.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    parserState.tokenData ?= buildTokenDataDictionary parserState.parser.tokens
    <span class="hljs-keyword">if</span> obj.locationData?
      objHash = buildLocationHash obj.locationData
      <span class="hljs-keyword">if</span> parserState.tokenData[objHash]?.comments?
        attachCommentsToNode parserState.tokenData[objHash].comments, obj
    obj

<span class="hljs-built_in">exports</span>.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function"><span class="hljs-params">(comments, node)</span> -&gt;</span>
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> comments? <span class="hljs-keyword">or</span> comments.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
  node.comments ?= []
  node.comments.push comments...</pre></div></div>
            
        </li>
        
        
        <li id="section-23">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-23">&#x00a7;</a>
              </div>
              <p>Convert jison location data to a string.
<code>obj</code> can be a token, or a locationData.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.locationDataToString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-string">&quot;2&quot;</span> <span class="hljs-keyword">of</span> obj) <span class="hljs-keyword">and</span> (<span class="hljs-string">&quot;first_line&quot;</span> <span class="hljs-keyword">of</span> obj[<span class="hljs-number">2</span>]) <span class="hljs-keyword">then</span> locationData = obj[<span class="hljs-number">2</span>]
  <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">&quot;first_line&quot;</span> <span class="hljs-keyword">of</span> obj <span class="hljs-keyword">then</span> locationData = obj

  <span class="hljs-keyword">if</span> locationData
    <span class="hljs-string">&quot;<span class="hljs-subst">#{locationData.first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.first_column + <span class="hljs-number">1</span>}</span>-&quot;</span> +
    <span class="hljs-string">&quot;<span class="hljs-subst">#{locationData.last_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.last_column + <span class="hljs-number">1</span>}</span>&quot;</span>
  <span class="hljs-keyword">else</span>
    <span class="hljs-string">&quot;No location data&quot;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-24">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-24">&#x00a7;</a>
              </div>
              <p>Generate a unique anonymous file name so we can distinguish source map cache
entries for any number of anonymous scripts.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.anonymousFileName = <span class="hljs-keyword">do</span> -&gt;
  n = <span class="hljs-number">0</span>
  -&gt;
    <span class="hljs-string">&quot;&lt;anonymous-<span class="hljs-subst">#{n++}</span>&gt;&quot;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-25">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-25">&#x00a7;</a>
              </div>
              <p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.baseFileName = <span class="hljs-function"><span class="hljs-params">(file, stripExt = <span class="hljs-literal">no</span>, useWinPathSep = <span class="hljs-literal">no</span>)</span> -&gt;</span>
  pathSep = <span class="hljs-keyword">if</span> useWinPathSep <span class="hljs-keyword">then</span> <span class="hljs-regexp">/\\|\//</span> <span class="hljs-keyword">else</span> <span class="hljs-regexp">/\//</span>
  parts = file.split(pathSep)
  file = parts[parts.length - <span class="hljs-number">1</span>]
  <span class="hljs-keyword">return</span> file <span class="hljs-keyword">unless</span> stripExt <span class="hljs-keyword">and</span> file.indexOf(<span class="hljs-string">&#x27;.&#x27;</span>) &gt;= <span class="hljs-number">0</span>
  parts = file.split(<span class="hljs-string">&#x27;.&#x27;</span>)
  parts.pop()
  parts.pop() <span class="hljs-keyword">if</span> parts[parts.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;coffee&#x27;</span> <span class="hljs-keyword">and</span> parts.length &gt; <span class="hljs-number">1</span>
  parts.join(<span class="hljs-string">&#x27;.&#x27;</span>)</pre></div></div>
            
        </li>
        
        
        <li id="section-26">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-26">&#x00a7;</a>
              </div>
              <p>Determine if a filename represents a CoffeeScript file.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.isCoffee = <span class="hljs-function"><span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
            
        </li>
        
        
        <li id="section-27">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-27">&#x00a7;</a>
              </div>
              <p>Determine if a filename represents a Literate CoffeeScript file.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.isLiterate = <span class="hljs-function"><span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
            
        </li>
        
        
        <li id="section-28">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-28">&#x00a7;</a>
              </div>
              <p>Throws a SyntaxError from a given location.
The error’s <code>toString</code> will return an error message following the “standard”
format <code>&lt;filename&gt;:&lt;line&gt;:&lt;col&gt;: &lt;message&gt;</code> plus the line with the error and a
marker showing where the error is.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.throwSyntaxError = <span class="hljs-function"><span class="hljs-params">(message, location)</span> -&gt;</span>
  error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span> message
  error.location = location
  error.toString = syntaxErrorToString</pre></div></div>
            
        </li>
        
        
        <li id="section-29">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-29">&#x00a7;</a>
              </div>
              <p>Instead of showing the compiler’s stacktrace, show our custom error message
(this is useful when the error bubbles up in Node.js applications that
compile CoffeeScript for example).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  error.stack = error.toString()

  <span class="hljs-keyword">throw</span> error</pre></div></div>
            
        </li>
        
        
        <li id="section-30">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-30">&#x00a7;</a>
              </div>
              <p>Update a compiler SyntaxError with source code information if it didn’t have
it already.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.updateSyntaxError = <span class="hljs-function"><span class="hljs-params">(error, code, filename)</span> -&gt;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-31">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-31">&#x00a7;</a>
              </div>
              <p>Avoid screwing up the <code>stack</code> property of other errors (i.e. possible bugs).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="hljs-keyword">if</span> error.toString <span class="hljs-keyword">is</span> syntaxErrorToString
    error.code <span class="hljs-keyword">or</span>= code
    error.filename <span class="hljs-keyword">or</span>= filename
    error.stack = error.toString()
  error
<span class="hljs-function">
<span class="hljs-title">syntaxErrorToString</span> = -&gt;</span>
  <span class="hljs-keyword">return</span> Error::toString.call @ <span class="hljs-keyword">unless</span> @code <span class="hljs-keyword">and</span> @location

  {first_line, first_column, last_line, last_column} = @location
  last_line ?= first_line
  last_column ?= first_column

  <span class="hljs-keyword">if</span> @filename?.startsWith <span class="hljs-string">&#x27;&lt;anonymous&#x27;</span>
    filename = <span class="hljs-string">&#x27;[stdin]&#x27;</span>
  <span class="hljs-keyword">else</span>
    filename = @filename <span class="hljs-keyword">or</span> <span class="hljs-string">&#x27;[stdin]&#x27;</span>

  codeLine = @code.split(<span class="hljs-string">&#x27;\n&#x27;</span>)[first_line]
  start    = first_column</pre></div></div>
            
        </li>
        
        
        <li id="section-32">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-32">&#x00a7;</a>
              </div>
              <p>Show only the first line on multi-line errors.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  end      = <span class="hljs-keyword">if</span> first_line <span class="hljs-keyword">is</span> last_line <span class="hljs-keyword">then</span> last_column + <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> codeLine.length
  marker   = codeLine[...start].replace(<span class="hljs-regexp">/[^\s]/g</span>, <span class="hljs-string">&#x27; &#x27;</span>) + repeat(<span class="hljs-string">&#x27;^&#x27;</span>, end - start)</pre></div></div>
            
        </li>
        
        
        <li id="section-33">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-33">&#x00a7;</a>
              </div>
              <p>Check to see if we’re running on a color-enabled TTY.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="hljs-keyword">if</span> process?
    colorsEnabled = process.stdout?.isTTY <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> process.env?.NODE_DISABLE_COLORS

  <span class="hljs-keyword">if</span> @colorful ? colorsEnabled
<span class="hljs-function">    <span class="hljs-title">colorize</span> = <span class="hljs-params">(str)</span> -&gt;</span> <span class="hljs-string">&quot;\x1B[1;31m<span class="hljs-subst">#{str}</span>\x1B[0m&quot;</span>
    codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
    marker   = colorize marker

  <span class="hljs-string">&quot;&quot;&quot;
    <span class="hljs-subst">#{filename}</span>:<span class="hljs-subst">#{first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{first_column + <span class="hljs-number">1</span>}</span>: error: <span class="hljs-subst">#{@message}</span>
    <span class="hljs-subst">#{codeLine}</span>
    <span class="hljs-subst">#{marker}</span>
  &quot;&quot;&quot;</span>

<span class="hljs-built_in">exports</span>.nameWhitespaceCharacter = <span class="hljs-function"><span class="hljs-params">(string)</span> -&gt;</span>
  <span class="hljs-keyword">switch</span> string
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27; &#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;space&#x27;</span>
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;\n&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;newline&#x27;</span>
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;\r&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;carriage return&#x27;</span>
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;\t&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;tab&#x27;</span>
    <span class="hljs-keyword">else</span> string

<span class="hljs-built_in">exports</span>.parseNumber = <span class="hljs-function"><span class="hljs-params">(string)</span> -&gt;</span>
  <span class="hljs-keyword">return</span> <span class="hljs-literal">NaN</span> <span class="hljs-keyword">unless</span> string?

  base = <span class="hljs-keyword">switch</span> string.charAt <span class="hljs-number">1</span>
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;b&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-number">2</span>
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;o&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-number">8</span>
    <span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;x&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-number">16</span>
    <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>

  <span class="hljs-keyword">if</span> base?
    <span class="hljs-built_in">parseInt</span> string[<span class="hljs-number">2.</span>.].replace(<span class="hljs-regexp">/_/g</span>, <span class="hljs-string">&#x27;&#x27;</span>), base
  <span class="hljs-keyword">else</span>
    <span class="hljs-built_in">parseFloat</span> string.replace(<span class="hljs-regexp">/_/g</span>, <span class="hljs-string">&#x27;&#x27;</span>)

<span class="hljs-built_in">exports</span>.isFunction = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object Function]&#x27;</span>
<span class="hljs-built_in">exports</span>.isNumber = isNumber = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object Number]&#x27;</span>
<span class="hljs-built_in">exports</span>.isString = isString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object String]&#x27;</span>
<span class="hljs-built_in">exports</span>.isBoolean = isBoolean = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> obj <span class="hljs-keyword">is</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">or</span> obj <span class="hljs-keyword">is</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">or</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object Boolean]&#x27;</span>
<span class="hljs-built_in">exports</span>.isPlainObject = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> <span class="hljs-keyword">typeof</span> obj <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;object&#x27;</span> <span class="hljs-keyword">and</span> !!obj <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-built_in">Array</span>.isArray(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isNumber(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isString(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isBoolean(obj)
<span class="hljs-function">
<span class="hljs-title">unicodeCodePointToUnicodeEscapes</span> = <span class="hljs-params">(codePoint)</span> -&gt;</span>
<span class="hljs-function">  <span class="hljs-title">toUnicodeEscape</span> = <span class="hljs-params">(val)</span> -&gt;</span>
    str = val.toString <span class="hljs-number">16</span>
    <span class="hljs-string">&quot;\\u<span class="hljs-subst">#{repeat <span class="hljs-string">&#x27;0&#x27;</span>, <span class="hljs-number">4</span> - str.length}</span><span class="hljs-subst">#{str}</span>&quot;</span>
  <span class="hljs-keyword">return</span> toUnicodeEscape(codePoint) <span class="hljs-keyword">if</span> codePoint &lt; <span class="hljs-number">0x10000</span></pre></div></div>
            
        </li>
        
        
        <li id="section-34">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-34">&#x00a7;</a>
              </div>
              <p>surrogate pair</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  high = <span class="hljs-built_in">Math</span>.floor((codePoint - <span class="hljs-number">0x10000</span>) / <span class="hljs-number">0x400</span>) + <span class="hljs-number">0xD800</span>
  low = (codePoint - <span class="hljs-number">0x10000</span>) % <span class="hljs-number">0x400</span> + <span class="hljs-number">0xDC00</span>
  <span class="hljs-string">&quot;<span class="hljs-subst">#{toUnicodeEscape(high)}</span><span class="hljs-subst">#{toUnicodeEscape(low)}</span>&quot;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-35">
            <div class="annotation">
              
              <div class="sswrap ">
                <a class="ss" href="#section-35">&#x00a7;</a>
              </div>
              <p>Replace <code>\u{...}</code> with <code>\uxxxx[\uxxxx]</code> in regexes without <code>u</code> flag</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.replaceUnicodeCodePointEscapes = <span class="hljs-function"><span class="hljs-params">(str, {flags, error, delimiter = <span class="hljs-string">&#x27;&#x27;</span>} = {})</span> -&gt;</span>
  shouldReplace = flags? <span class="hljs-keyword">and</span> <span class="hljs-string">&#x27;u&#x27;</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> flags
  str.replace UNICODE_CODE_POINT_ESCAPE, <span class="hljs-function"><span class="hljs-params">(match, escapedBackslash, codePointHex, offset)</span> -&gt;</span>
    <span class="hljs-keyword">return</span> escapedBackslash <span class="hljs-keyword">if</span> escapedBackslash

    codePointDecimal = <span class="hljs-built_in">parseInt</span> codePointHex, <span class="hljs-number">16</span>
    <span class="hljs-keyword">if</span> codePointDecimal &gt; <span class="hljs-number">0x10ffff</span>
      error <span class="hljs-string">&quot;unicode code point escapes greater than \\u{10ffff} are not allowed&quot;</span>,
        offset: offset + delimiter.length
        length: codePointHex.length + <span class="hljs-number">4</span>
    <span class="hljs-keyword">return</span> match <span class="hljs-keyword">unless</span> shouldReplace

    unicodeCodePointToUnicodeEscapes codePointDecimal

UNICODE_CODE_POINT_ESCAPE = <span class="hljs-regexp">///
  ( \\\\ )        <span class="hljs-comment"># Make sure the escape isn’t escaped.</span>
  |
  \\u\{ ( [\da-fA-F]+ ) \}
///</span>g</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
